<a href='https://github.com/angular/angular.js/edit/v1.5.x/docs/content/guide/accessibility.ngdoc?message=docs(guide%2FAccessibility)%3A%20describe%20your%20change...' class='improve-docs btn btn-primary'><i class="glyphicon glyphicon-edit">&nbsp;</i>Improve this Doc</a>


<h1 id="accessibility-with-ngaria">Accessibility with ngAria</h1>
<p>The goal of ngAria is to improve Angular&#39;s default accessibility by enabling common
<a href="http://www.w3.org/TR/wai-aria/">ARIA</a> attributes that convey state or semantic information for
assistive technologies used by persons with disabilities.</p>
<h2 id="including-ngaria">Including ngAria</h2>
<p>Using <a href="api/ngAria">ngAria</a> is as simple as requiring the ngAria module in your application. ngAria hooks into
standard AngularJS directives and quietly injects accessibility support into your application
at runtime.</p>
<pre><code class="lang-js">angular.module(&#39;myApp&#39;, [&#39;ngAria&#39;])...
</code></pre>
<h3 id="using-ngaria">Using ngAria</h3>
<p>Most of what ngAria does is only visible &quot;under the hood&quot;. To see the module in action, once you&#39;ve
added it as a dependency, you can test a few things:</p>
<ul>
<li>Using your favorite element inspector, look for attributes added by ngAria in your own code.</li>
<li>Test using your keyboard to ensure <code>tabindex</code> is used correctly.</li>
<li>Fire up a screen reader such as VoiceOver or NVDA to check for ARIA support.
<a href="http://webaim.org/articles/screenreader_testing/">Helpful screen reader tips.</a></li>
</ul>
<h2 id="supported-directives">Supported directives</h2>
<p>Currently, ngAria interfaces with the following directives:</p>
<ul>
<li><a href="guide/accessibility#ngmodel">ngModel</a></li>
<li><a href="guide/accessibility#ngdisabled">ngDisabled</a></li>
<li><a href="guide/accessibility#ngrequired">ngRequired</a></li>
<li><a href="guide/accessibility#ngreadonly">ngReadonly</a></li>
<li><a href="guide/accessibility#ngvaluechecked">ngChecked</a></li>
<li><a href="guide/accessibility#ngvaluechecked">ngValue</a></li>
<li><a href="guide/accessibility#ngshow">ngShow</a></li>
<li><a href="guide/accessibility#nghide">ngHide</a></li>
<li><a href="guide/accessibility#ngclick">ngClick</a></li>
<li><a href="guide/accessibility#ngdblclick">ngDblClick</a></li>
<li><a href="guide/accessibility#ngmessages">ngMessages</a></li>
</ul>
<h2 id="ngmodel">ngModel</h2>

<p>Much of ngAria&#39;s heavy lifting happens in the <a href="api/ng/directive/ngModel">ngModel</a>
directive. For elements using ngModel, special attention is paid by ngAria if that element also
has a role or type of <code>checkbox</code>, <code>radio</code>, <code>range</code> or <code>textbox</code>.</p>
<p>For those elements using ngModel, ngAria will dynamically bind and update the following ARIA
attributes (if they have not been explicitly specified by the developer):</p>
<ul>
<li>aria-checked</li>
<li>aria-valuemin</li>
<li>aria-valuemax</li>
<li>aria-valuenow</li>
<li>aria-invalid</li>
<li>aria-required</li>
<li>aria-readonly</li>
</ul>
<h3 id="example">Example</h3>
<p>

<div>
  <plnkr-opener example-path="examples/example-example2"></plnkr-opener>

  <div class="runnable-example"
      path="examples/example-example2"
      module="ngAria_ngModelExample"
      deps="angular-aria.js">

  
    <div class="runnable-example-file" 
      name="index.html"
      language="html"
      type="html">
      <pre><code>&lt;form ng-controller=&quot;formsController&quot;&gt;&#10;  &lt;some-checkbox role=&quot;checkbox&quot; ng-model=&quot;checked&quot; ng-class=&quot;{active: checked}&quot;&#10;    ng-disabled=&quot;isDisabled&quot; ng-click=&quot;toggleCheckbox()&quot;&#10;    aria-label=&quot;Custom Checkbox&quot; show-attrs&gt;&#10;    &lt;span class=&quot;icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&#10;    Custom Checkbox&#10;  &lt;/some-checkbox&gt;&#10;&lt;/form&gt;</code></pre>
    </div>
  
    <div class="runnable-example-file" 
      name="script.js"
      language="js"
      type="js">
      <pre><code>var app = angular.module(&#39;ngAria_ngModelExample&#39;, [&#39;ngAria&#39;])&#10;.controller(&#39;formsController&#39;, function($scope){&#10;  $scope.checked = false;&#10;  $scope.toggleCheckbox = function(){&#10;    $scope.checked = !$scope.checked;&#10;  };&#10;})&#10;.directive(&#39;someCheckbox&#39;, function(){&#10;  return {&#10;    restrict: &#39;E&#39;,&#10;    link: function($scope, $el, $attrs) {&#10;      $el.on(&#39;keypress&#39;, function(event){&#10;        event.preventDefault();&#10;        if(event.keyCode === 32 || event.keyCode === 13){&#10;          $scope.toggleCheckbox();&#10;          $scope.$apply();&#10;        }&#10;      });&#10;    }&#10;  };&#10;})&#10;.directive(&#39;showAttrs&#39;, function() {&#10;  return function($scope, $el, $attrs) {&#10;    var pre = document.createElement(&#39;pre&#39;);&#10;    $el.after(pre);&#10;    $scope.$watch(function() {&#10;      var $attrs = {};&#10;      Array.prototype.slice.call($el[0].attributes, 0).forEach(function(item) {&#10;        if (item.name !== &#39;show-$attrs&#39;) {&#10;          $attrs[item.name] = item.value;&#10;        }&#10;      });&#10;      return $attrs;&#10;    }, function(newAttrs, oldAttrs) {&#10;      pre.textContent = JSON.stringify(newAttrs, null, 2);&#10;    }, true);&#10;  };&#10;});</code></pre>
    </div>
  
    <div class="runnable-example-file" 
      name="style.css"
      language="css"
      type="css">
      <pre><code>[role=checkbox] {&#10;  cursor: pointer;&#10;  display: inline-block;&#10;}&#10;[role=checkbox] .icon:before {&#10;  content: &#39;\2610&#39;;&#10;  display: inline-block;&#10;  font-size: 2em;&#10;  line-height: 1;&#10;  vertical-align: middle;&#10;  speak: none;&#10;}&#10;[role=checkbox].active .icon:before {&#10;  content: &#39;\2611&#39;;&#10;}&#10;pre {&#10;  white-space: pre-wrap;&#10;}</code></pre>
    </div>
  

    <iframe class="runnable-example-frame" src="examples/example-example2/index.html" name="example-example2"></iframe>
  </div>
</div>


</p>
<p>ngAria will also add <code>tabIndex</code>, ensuring custom elements with these roles will be reachable from
the keyboard. It is still up to <strong>you</strong> as a developer to <strong>ensure custom controls will be
accessible</strong>. As a rule, any time you create a widget involving user interaction, be sure to test
it with your keyboard and at least one mobile and desktop screen reader.</p>
<h2 id="ngvaluechecked">ngValue and ngChecked</h2>

<p>To ease the transition between native inputs and custom controls, ngAria now supports
<a href="api/ng/directive/ngValue">ngValue</a> and <a href="api/ng/directive/ngChecked">ngChecked</a>.
The original directives were created for native inputs only, so ngAria extends
support to custom elements by managing <code>aria-checked</code> for accessibility.</p>
<h3 id="example">Example</h3>
<pre><code class="lang-html">&lt;custom-checkbox ng-checked=&quot;val&quot;&gt;&lt;/custom-checkbox&gt;
&lt;custom-radio-button ng-value=&quot;val&quot;&gt;&lt;/custom-radio-button&gt;
</code></pre>
<p>Becomes:</p>
<pre><code class="lang-html">&lt;custom-checkbox ng-checked=&quot;val&quot; aria-checked=&quot;true&quot;&gt;&lt;/custom-checkbox&gt;
&lt;custom-radio-button ng-value=&quot;val&quot; aria-checked=&quot;true&quot;&gt;&lt;/custom-radio-button&gt;
</code></pre>
<h2 id="ngdisabled">ngDisabled</h2>

<p>The <code>disabled</code> attribute is only valid for certain elements such as <code>button</code>, <code>input</code> and
<code>textarea</code>. To properly disable custom element directives such as <code>&lt;md-checkbox&gt;</code> or <code>&lt;taco-tab&gt;</code>,
using ngAria with <a href="api/ng/directive/ngDisabled">ngDisabled</a> will also
add <code>aria-disabled</code>. This tells assistive technologies when a non-native input is disabled, helping
custom controls to be more accessible.</p>
<h3 id="example">Example</h3>
<pre><code class="lang-html">&lt;md-checkbox ng-disabled=&quot;disabled&quot;&gt;&lt;/md-checkbox&gt;
</code></pre>
<p>Becomes:</p>
<pre><code class="lang-html">&lt;md-checkbox disabled aria-disabled=&quot;true&quot;&gt;&lt;/md-checkbox&gt;
</code></pre>
<div class="alert alert-info">
You can check whether a control is legitimately disabled for a screen reader by visiting
<a href="chrome://accessibility">chrome://accessibility</a> and inspecting <a href="http://www.paciellogroup.com/blog/2015/01/the-browser-accessibility-tree/">the accessibility tree</a>.
</div>

<h2 id="ngrequired">ngRequired</h2>

<p>The boolean <code>required</code> attribute is only valid for native form controls such as <code>input</code> and
<code>textarea</code>. To properly indicate custom element directives such as <code>&lt;md-checkbox&gt;</code> or <code>&lt;custom-input&gt;</code>
as required, using ngAria with <a href="api/ng/directive/ngRequired">ngRequired</a> will also add
<code>aria-required</code>. This tells accessibility APIs when a custom control is required.</p>
<h3 id="example">Example</h3>
<pre><code class="lang-html">&lt;md-checkbox ng-required=&quot;val&quot;&gt;&lt;/md-checkbox&gt;
</code></pre>
<p>Becomes:</p>
<pre><code class="lang-html">&lt;md-checkbox ng-required=&quot;val&quot; aria-required=&quot;true&quot;&gt;&lt;/md-checkbox&gt;
</code></pre>
<h2 id="ngreadonly">ngReadonly</h2>

<p>The boolean <code>readonly</code> attribute is only valid for native form controls such as <code>input</code> and
<code>textarea</code>. To properly indicate custom element directives such as <code>&lt;md-checkbox&gt;</code> or <code>&lt;custom-input&gt;</code>
as required, using ngAria with <a href="api/ng/directive/ngReadonly">ngReadonly</a> will also add
<code>aria-readonly</code>. This tells accessibility APIs when a custom control is read-only.</p>
<h3 id="example">Example</h3>
<pre><code class="lang-html">&lt;md-checkbox ng-readonly=&quot;val&quot;&gt;&lt;/md-checkbox&gt;
</code></pre>
<p>Becomes:</p>
<pre><code class="lang-html">&lt;md-checkbox ng-readonly=&quot;val&quot; aria-readonly=&quot;true&quot;&gt;&lt;/md-checkbox&gt;
</code></pre>
<h2 id="ngshow">ngShow</h2>

<p>The <a href="api/ng/directive/ngShow">ngShow</a> directive shows or hides the
given HTML element based on the expression provided to the <code>ngShow</code> attribute. The element is
shown or hidden by removing or adding the <code>.ng-hide</code> CSS class onto the element.</p>
<p>In its default setup, ngAria for <code>ngShow</code> is actually redundant. It toggles <code>aria-hidden</code> on the
directive when it is hidden or shown. However, the default CSS of <code>display: none !important</code>,
already hides child elements from a screen reader. It becomes more useful when the default
CSS is overridden with properties that don’t affect assistive technologies, such as <code>opacity</code>
or <code>transform</code>. By toggling <code>aria-hidden</code> dynamically with ngAria, we can ensure content visually
hidden with this technique will not be read aloud in a screen reader.</p>
<p>One caveat with this combination of CSS and <code>aria-hidden</code>: you must also remove links and other
interactive child elements from the tab order using <code>tabIndex=“-1”</code> on each control. This ensures
screen reader users won&#39;t accidentally focus on &quot;mystery elements&quot;. Managing tab index on every
child control can be complex and affect performance, so it’s best to just stick with the default
<code>display: none</code> CSS. See the <a href="http://www.w3.org/TR/aria-in-html/#fourth-rule-of-aria-use">fourth rule of ARIA use</a>.</p>
<h3 id="example">Example</h3>
<pre><code class="lang-css">.ng-hide {
  display: block;
  opacity: 0;
}
</code></pre>
<pre><code class="lang-html">&lt;div ng-show=&quot;false&quot; class=&quot;ng-hide&quot; aria-hidden=&quot;true&quot;&gt;&lt;/div&gt;
</code></pre>
<p>Becomes:</p>
<pre><code class="lang-html">&lt;div ng-show=&quot;true&quot; aria-hidden=&quot;false&quot;&gt;&lt;/div&gt;
</code></pre>
<p><em>Note: Child links, buttons or other interactive controls must also be removed from the tab order.</em></p>
<h2 id="nghide">ngHide</h2>

<p>The <a href="api/ng/directive/ngHide">ngHide</a> directive shows or hides the
given HTML element based on the expression provided to the <code>ngHide</code> attribute. The element is
shown or hidden by removing or adding the <code>.ng-hide</code> CSS class onto the element.</p>
<p>The default CSS for <code>ngHide</code>, the inverse method to <code>ngShow</code>, makes ngAria redundant. It toggles
<code>aria-hidden</code> on the directive when it is hidden or shown, but the content is already hidden with
<code>display: none</code>. See explanation for <a href="guide/accessibility#ngshow">ngShow</a> when overriding the default CSS.</p>
<h2><span id="ngclick">ngClick</span> and <span id="ngdblclick">ngDblclick</span></h2>
If <code>ng-click</code> or <code>ng-dblclick</code> is encountered, ngAria will add <code>tabindex=&quot;0&quot;</code> to any element not in
a node blacklist:

 <em> Button
 </em> Anchor
 <em> Input
 </em> Textarea
 <em> Select
 </em> Details/Summary

To fix widespread accessibility problems with <code>ng-click</code> on <code>div</code> elements, ngAria will
dynamically bind a keypress event by default as long as the element isn&#39;t in the node blacklist.
You can turn this functionality on or off with the <code>bindKeypress</code> configuration option.

ngAria will also add the <code>button</code> role to communicate to users of assistive technologies. This can
be disabled with the <code>bindRoleForClick</code> configuration option.

For <code>ng-dblclick</code>, you must still manually add <code>ng-keypress</code> and a role to non-interactive elements
such as <code>div</code> or <code>taco-button</code> to enable keyboard access.

<h3>Example</h3>
<code>html
&lt;div ng-click=&quot;toggleMenu()&quot;&gt;&lt;/div&gt;</code>

Becomes:
<code>html
&lt;div ng-click=&quot;toggleMenu()&quot; tabindex=&quot;0&quot;&gt;&lt;/div&gt;</code>

<h2 id="ngmessages">ngMessages</h2>

<p>The ngMessages module makes it easy to display form validation or other messages with priority
sequencing and animation. To expose these visual messages to screen readers,
ngAria injects <code>aria-live=&quot;assertive&quot;</code>, causing them to be read aloud any time a message is shown,
regardless of the user&#39;s focus location.</p>
<h3 id="example">Example</h3>
<pre><code class="lang-html">&lt;div ng-messages=&quot;myForm.myName.$error&quot;&gt;
  &lt;div ng-message=&quot;required&quot;&gt;You did not enter a field&lt;/div&gt;
  &lt;div ng-message=&quot;maxlength&quot;&gt;Your field is too long&lt;/div&gt;
&lt;/div&gt;
</code></pre>
<p>Becomes:</p>
<pre><code class="lang-html">&lt;div ng-messages=&quot;myForm.myName.$error&quot; aria-live=&quot;assertive&quot;&gt;
  &lt;div ng-message=&quot;required&quot;&gt;You did not enter a field&lt;/div&gt;
  &lt;div ng-message=&quot;maxlength&quot;&gt;Your field is too long&lt;/div&gt;
&lt;/div&gt;
</code></pre>
<h2 id="disabling-attributes">Disabling attributes</h2>
<p>The attribute magic of ngAria may not work for every scenario. To disable individual attributes,
you can use the <a href="api/ngAria/provider/$ariaProvider#config">config</a> method. Just keep in mind this will
tell ngAria to ignore the attribute globally.</p>
<p>

<div>
  <plnkr-opener example-path="examples/example-example3"></plnkr-opener>

  <div class="runnable-example"
      path="examples/example-example3"
      module="ngAria_ngClickExample"
      deps="angular-aria.js">

  
    <div class="runnable-example-file" 
      name="index.html"
      language="html"
      type="html">
      <pre><code> &lt;div ng-click=&quot;someFunction&quot; show-attrs&gt;&#10;   &amp;lt;div&amp;gt; with ng-click and bindRoleForClick, tabindex set to false&#10; &lt;/div&gt;&#10;&lt;script&gt;&#10; angular.module(&#39;ngAria_ngClickExample&#39;, [&#39;ngAria&#39;], function config($ariaProvider) {&#10;   $ariaProvider.config({&#10;     bindRoleForClick: false,&#10;     tabindex: false&#10;   });&#10; })&#10; .directive(&#39;showAttrs&#39;, function() {&#10;   return function(scope, el, attrs) {&#10;     var pre = document.createElement(&#39;pre&#39;);&#10;     el.after(pre);&#10;     scope.$watch(function() {&#10;       var attrs = {};&#10;       Array.prototype.slice.call(el[0].attributes, 0).forEach(function(item) {&#10;         if (item.name !== &#39;show-attrs&#39;) {&#10;           attrs[item.name] = item.value;&#10;         }&#10;       });&#10;       return attrs;&#10;     }, function(newAttrs, oldAttrs) {&#10;       pre.textContent = JSON.stringify(newAttrs, null, 2);&#10;     }, true);&#10;   }&#10; });&#10;&lt;/script&gt;</code></pre>
    </div>
  

    <iframe class="runnable-example-frame" src="examples/example-example3/index.html" name="example-example3"></iframe>
  </div>
</div>


</p>
<h2 id="common-accessibility-patterns">Common Accessibility Patterns</h2>
<p>Accessibility best practices that apply to web apps in general also apply to Angular.</p>
<ul>
<li><strong>Text alternatives</strong>: Add alternate text content to make visual information accessible using
<a href="http://www.w3.org/TR/html-alt-techniques/">these W3C guidelines</a>. The appropriate technique
depends on the specific markup but can be accomplished using offscreen spans, <code>aria-label</code> or
label elements, image <code>alt</code> attributes, <code>figure</code>/<code>figcaption</code> elements and more.</li>
<li><strong>HTML Semantics</strong>: If you&#39;re creating custom element directives, Web Components or HTML in
general, use native elements wherever possible to utilize built-in events and properties.
Alternatively, use ARIA to communicate semantic meaning. See <a href="http://www.w3.org/TR/aria-in-html/#notes-on-aria-use-in-html">notes on ARIA use</a>.</li>
<li><strong>Focus management</strong>: Guide the user around the app as views are appended/removed.
Focus should <em>never</em> be lost, as this causes unexpected behavior and much confusion (referred to
as &quot;freak-out mode&quot;).</li>
<li><strong>Announcing changes</strong>: When filtering or other UI messaging happens away from the user&#39;s focus,
notify with <a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions">ARIA Live Regions</a>.</li>
<li><strong>Color contrast and scale</strong>: Make sure content is legible and interactive controls are usable
at all screen sizes. Consider configurable UI themes for people with color blindness, low vision
or other visual impairments.</li>
<li><strong>Progressive enhancement</strong>: Some users do not browse with JavaScript enabled or do not have
the latest browser. An accessible message about site requirements can inform users and improve
the experience.</li>
</ul>
<h2 id="additional-resources">Additional Resources</h2>
<ul>
<li><a href="http://www.w3.org/TR/aria-in-html/">Using ARIA in HTML</a></li>
<li><a href="https://www.youtube.com/watch?v=dmYDggEgU-s&amp;list=UUEGUP3TJJfMsEM_1y8iviSQ">AngularJS Accessibility at ngEurope</a></li>
<li><a href="http://webaim.org/articles/screenreader_testing/">Testing with Screen Readers</a></li>
<li><a href="https://chrome.google.com/webstore/detail/accessibility-developer-t/fpkknkljclfencbdbgkenhalefipecmb?hl=en">Chrome Accessibility Developer Tools</a></li>
<li><a href="http://www.w3.org/wiki/Accessibility_testing">W3C Accessibility Testing</a></li>
<li><a href="http://webaim.org">WebAIM</a></li>
<li><a href="http://a11yproject.com">A11y Project</a></li>
</ul>


